/**
 * Project: iuc.common
 * 
 * File Created at 2010-4-13
 * $Id$
 * 
 * Copyright 2008 Alibaba.com Croporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Alibaba Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Alibaba.com.
 */
package com.ymkyve.complex.common;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang.StringUtils;

/**
 * @description:http请求调用类
 * @author gaoliang
 * @date 2010-4-13
 * @version 1.0
 */
public class HttpInvokerUtil {

    private final static int    connectionTimeOut = 5000;

    private final static String default_encode    = "UTF-8";

    /**
     * httpclient get方法
     * 
     * @param url
     * @return
     */
    public static String invokeWithGetMethod(String baseUrl, Map<String, String> params,
                                             String encoding) throws HttpException, IOException {
        //设置编码
        if (StringUtils.isEmpty(encoding)) {
            encoding = default_encode;
        }

        // 拼接get请求的url
        String url = spliceGetMothodUrl(baseUrl, params, encoding);
        HttpClient httpClient = new HttpClient();
        //设置连接超时
        httpClient.getParams().setConnectionManagerTimeout(connectionTimeOut);
        //使用get方法
        GetMethod getMethod = new GetMethod(url);
        //设置请求重试处理，用的是默认的重试处理：请求三次
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler());
        //设置字符编码
        getMethod.getParams().setContentCharset(encoding);

        InputStream inputStream = null;
        ByteArrayOutputStream bos = null;
        try {
            //建立连接并获取数据
            int statusCode = httpClient.executeMethod(getMethod);
            if (statusCode == HttpStatus.SC_OK) {
                inputStream = getMethod.getResponseBodyAsStream();
                bos = new ByteArrayOutputStream();
                byte[] bRead = new byte[1024];
                int iRead;
                while ((iRead = inputStream.read(bRead, 0, 1024)) != -1) {
                    bos.write(bRead, 0, iRead);
                }
                return new String(bos.toByteArray(), encoding);
            }
            //不正常连接
            throw new IOException("invokeWithGetMethod error:" + getMethod.getStatusLine()
                    + ",url: " + url);

        } catch (HttpException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        } finally {
            getMethod.releaseConnection();
            if (inputStream != null)
                inputStream.close();
            if (bos != null)
                bos.close();
        }

    }

    /**
     * httpclient post方法
     * 
     * @param url
     * @param params
     * @return
     */
    public static String invokeWithPostMethod(String url, Map<String, String> params,
                                              String encoding) throws HttpException, IOException {

        //设置编码
        if (StringUtils.isEmpty(encoding)) {
            encoding = default_encode;
        }
        HttpClient httpClient = new HttpClient();
        //设置连接超时
        httpClient.getParams().setConnectionManagerTimeout(connectionTimeOut);
        //使用post方法
        PostMethod postMethod = new PostMethod(url);
        //设置请求重试处理，用的是默认的重试处理：请求三次
        postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler());
        //设置编码
        postMethod.getParams().setContentCharset(encoding);
        //设置参数
        for (Entry<String, String> entry : params.entrySet()) {
            postMethod.addParameter(entry.getKey(), entry.getValue());
        }

        InputStream inputStream = null;
        ByteArrayOutputStream bos = null;
        try {
            //建立连接并获取数据
            int statusCode = httpClient.executeMethod(postMethod);
            if (statusCode == HttpStatus.SC_OK) {
                inputStream = postMethod.getResponseBodyAsStream();
                bos = new ByteArrayOutputStream();
                byte[] bRead = new byte[1024];
                int iRead;
                while ((iRead = inputStream.read(bRead, 0, 1024)) != -1) {
                    bos.write(bRead, 0, iRead);
                }
                return new String(bos.toByteArray(), encoding);
            }
            //不正常连接
            throw new IOException("invokeWithPostMethod error:" + postMethod.getStatusLine()
                    + ",url: " + url);

        } catch (HttpException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        } finally {
            postMethod.releaseConnection();
            if (inputStream != null)
                inputStream.close();
            if (bos != null)
                bos.close();
        }

    }

    /**
     * 对参数进行URL编码
     * 
     * @param param 参数
     * @return URLEncode 结果
     */
    public static String encode(String param, String encoding) {
        if (param == null) {
            return "";
        } else {
            param = param.trim();
            try {
                return URLEncoder.encode(param, encoding);
            } catch (UnsupportedEncodingException e) {
                return param;
            }
        }
    }

    /**
     * 拼装get请求的参数，组装返回完整url
     * 
     * @param url
     * @param params
     * @param encoding
     * @return
     */
    private static String spliceGetMothodUrl(String url, Map<String, String> params, String encoding) {
        if (params == null || params.isEmpty()) {
            return url;
        }
        //判断最后一位是否为/
        while (url.endsWith("/")) {
            url = url.substring(0, url.length() - 1);
        }

        StringBuffer sb = new StringBuffer();
        if (!url.contains("?")) {
            sb.append("?");
        } else if (url.contains("=") && !url.endsWith("&")) {
            sb.append("&");
        }
        for (Entry<String, String> entry : params.entrySet()) {
            String param = encode(entry.getValue(), encoding);
            sb.append(entry.getKey()).append("=").append(param).append("&");
        }
        sb.deleteCharAt(sb.length() - 1);
        return new StringBuffer(url + sb.toString()).toString();
    }
}
